package com.hulk.dryad.web.filter;

import com.hulk.dryad.common.constant.enums.BEC;
import com.hulk.dryad.common.exception.SecurityRteException;
import com.hulk.dryad.common.util.RequestUtils;
import com.hulk.dryad.common.util.SignUtil;
import com.hulk.dryad.manage.provider.cache.SignKeyCache;
import lombok.extern.slf4j.Slf4j;

import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Map;


/**
 * Request包装类
 * <p>
 * 1.JSON签名check
 * 2.拓展requestbody无限获取(HttpServletRequestWrapper只能获取一次)
 * </p>
 *
 * @author hulk
 */
@Slf4j
public class SignatureServletRequestWrapper extends HttpServletRequestWrapper {

    /**
     * 没被包装过的HttpServletRequest（特殊场景,需要自己过滤）
     */


    SignKeyCache signKeyCache;

    private final byte[] body;

    public SignatureServletRequestWrapper(HttpServletRequest request, SignKeyCache signKeyCache) throws IOException {
        super(request);
        this.signKeyCache = signKeyCache;
        body = RequestUtils.getByteBody(request);
    }

    @Override
    public BufferedReader getReader()  {
        return new BufferedReader(new InputStreamReader(getInputStream()));
    }

    @Override
    public ServletInputStream getInputStream()  {
        final ByteArrayInputStream bais = new ByteArrayInputStream(body);

        return new ServletInputStream() {

            @Override
            public int read()  {
                return bais.read();
            }

            @Override
            public boolean isFinished() {
                return false;
            }

            @Override
            public boolean isReady() {
                return false;
            }

            @Override
            public void setReadListener(ReadListener readListener) {

            }
        };
    }


    /**
     * 验证签名和防止重放攻击
     *
     * @param param
     */
    protected void check(Map param) {

        String key = signKeyCache.getSignKey();
        String signature = String.valueOf(param.get(SignUtil.SIGNATURE));
        boolean sflag = SignUtil.verify(param, signature, key);
        if (!sflag) {
            throw new SecurityRteException(BEC.E_2005);
        }

//		if(StrUtil.isBlank(nonce)){
//			throw new SecurityRteException(BEC.E_2014);
//		}
//		RepeatAttackHandler attack = 	SpringContextHolder.getBean(RepeatAttackHandler.class);
//		boolean aflag = attack.isRepeatAttack(nonce);
//		if (aflag) {
//			throw new SecurityRteException(BEC.E_2014);
//		}

    }

}